package com.strongbj.iot.devices.ru.response.service.impl;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service;

import com.strongbj.iot.devices.ru.response.entity.UInfoEntity;
import com.strongbj.iot.devices.ru.response.service.ICabinetService;

/**
 * 机柜相关服务，此类中维护了一个机柜信息的MAP
 * @author yuzhantao
 *
 */
@Service("cabinetService")
public class CabinetCacheService implements ICabinetService {
	private static Logger logger = LogManager.getLogger(CabinetCacheService.class.getName());
	/**
	 * 最大u位扫描的数据条数
	 */
	private final static int MAX_U_SCAN_HISTORY_DATA_SIZE = 5;
	/**
	 * u位扫描历史列表
	 */
	private Map<String, List<String>> uScanHistoryMap = new ConcurrentHashMap<>();
	private volatile Map<String, UInfoEntity> cabinetInfoMap = new ConcurrentHashMap<>();
	
	@Override
	public void setDoorState(String devAddr, byte state) {
		UInfoEntity civ = this.findCabinetInfo(devAddr);
		for(UInfoEntity.DevAddr dev : civ.getDevAddrList()){
			if(dev.getDevAddrCode().equals(devAddr)) {
				dev.setDoorState(state);
				dev.setDoorStateUpdateTime(new Date());
				logger.info("#info setDoorState 设置开关门："+state);
				break;
			}
		}
	}

	@Override
	public UInfoEntity findCabinetInfo(String devAddr) {
		UInfoEntity civ =  cabinetInfoMap.get(devAddr);
		if(civ==null){
			civ = new UInfoEntity();
			UInfoEntity.DevAddr dev = civ.new DevAddr();
			dev.setDevAddrCode(devAddr);
			dev.setDoorState((byte)0);
			dev.setCheckUpdateTime(new Date());
			dev.setDoorStateUpdateTime(new Date());
			civ.getDevAddrList().add(dev);
			cabinetInfoMap.put(devAddr, civ);
			logger.info("#info findCabinetInfo 创建新机柜信息 ("+devAddr+")");
		}
		return civ;
	}

	@Override
	public Collection<UInfoEntity> findAllCabinetInfoList() {
		return cabinetInfoMap.values();
	}

	@Override
	public void removeCabinetInfo(String devAddr) {
		cabinetInfoMap.remove(devAddr);
		logger.info("#info removeCabinetInfo("+devAddr+")");
	}
	
	@Override
	public void updateScanUInfo(UInfoEntity entity) {
		UInfoEntity.DevAddr newDev = entity.getDevAddrList().get(0);
		UInfoEntity civ = this.findCabinetInfo(newDev.getDevAddrCode());
		UInfoEntity.DevAddr cacheDev = civ.getDevAddrList().get(0);
		cacheDev.setUdevInfo(newDev.getUdevInfo());
		cacheDev.setCheckUpdateTime(new Date());
		logger.info("#info CabinetCacheService.updateScanUInfo("+newDev.getDevAddrCode()+")");
	}

	public void addCheckCabinetInfo(String devAddr, Map<Byte, String> uMap) {
		devAddr = devAddr.toUpperCase();
		String code = this.uMapToString(uMap);
		if (this.uScanHistoryMap.containsKey(devAddr) == false) {
			this.uScanHistoryMap.put(devAddr, new ArrayList<String>());
		}
		List<String> history = this.uScanHistoryMap.get(devAddr);
		if (history.size() != MAX_U_SCAN_HISTORY_DATA_SIZE) {
			history.add(code);
		}
	}
	
	/**
	 * 检查机柜信息是否可以上传
	 * @param devAddr
	 * @param uMap
	 * @return
	 */
	@Override
	public boolean checkCabinetInfoIsPush(String devAddr, Map<Byte, String> uMap) {
		devAddr = devAddr.toUpperCase();
		String code = this.uMapToString(uMap);
		if (this.uScanHistoryMap.containsKey(devAddr) == false) {
			return false;
		}

		List<String> history = this.uScanHistoryMap.get(devAddr);
		
		Map<String, Integer> statistics = new HashMap<>();
		for (int i = 0; i < history.size(); i++) {
			if (statistics.containsKey(history.get(i))) {
				int count = statistics.get(history.get(i));
				statistics.put(history.get(i), count+1);
			} else {
				statistics.put(history.get(i), 1);
			}
		}
		
		logger.info("=====================================================");
		logger.info("当前硬件编码="+devAddr);
		logger.info("当前特征编码="+code);
		logger.info("-----------------------------------------------------");
		for (Map.Entry<String, Integer> entity : statistics.entrySet()) {
			logger.info("概率统计="+entity.getValue()+"     特征编码="+entity.getKey());
		}
		logger.info("=====================================================");
		
		if (history.size() != MAX_U_SCAN_HISTORY_DATA_SIZE) {
			logger.info("硬件编号["+devAddr+"]的概率统计数量="+history.size()+"    小于指定的"+MAX_U_SCAN_HISTORY_DATA_SIZE+"条，因此不符合条件");
			return false;
		}
		
		String maxCode="";
		int maxCount = 0;
		for (Map.Entry<String, Integer> entity : statistics.entrySet()) {
			if (entity.getValue() > maxCount) {
				maxCode = entity.getKey();
				maxCount = entity.getValue();
			}
		}
		statistics.clear();
		history.remove(0);
		history.add(code);
		return code.equals(maxCode);
	}

	private String uMapToString(Map<Byte, String> uMap) {
		Map<Byte, String> map = sortMapByKey(uMap);
		StringBuffer sb = new StringBuffer();

		for (Map.Entry<Byte, String> entry : map.entrySet()) {
			sb.append(entry.getKey());
			sb.append("-");
			sb.append(entry.getValue());
			sb.append(";");
		}
		return sb.toString().toUpperCase();
	}

	private Map<Byte, String> sortMapByKey(Map<Byte, String> map) {
		Map<Byte, String> sortMap = new TreeMap<Byte, String>(new MapKeyComparator());
		sortMap.putAll(map);
		return sortMap;
	}
}
